<template>
<div class="uploads_class">
    <a-row>
        <div class="" style="margin-top: 5px;"></div>
        <a-tabs default-active-key="1" @change="callback">
        <a-tab-pane key="1" tab="我的网盘">
            
            Content of Tab Pane 1
        </a-tab-pane>
        <a-tab-pane key="2" tab="传输列表" force-render>
            Content of Tab Pane 2
        </a-tab-pane>
        <a-tab-pane key="3" tab="我的共享" force-render>
            Content of Tab Pane 2
        </a-tab-pane>
        <a-tab-pane key="4" tab="共享资源">
            Content of Tab Pane 3
        </a-tab-pane>
        <a-tab-pane key="5" tab="我的设置">
            Content of Tab Pane 4
        </a-tab-pane>
        </a-tabs>
    </a-row>

    

    <a-menu v-model="current" mode="horizontal">
        <a-menu-item key="netstore">我的网盘 
        </a-menu-item>
        <a-menu-item key="app" > 传输列表 </a-menu-item>
        <a-menu-item key="files" > 共享资源 </a-menu-item>
        <a-menu-item key="setting" > 我的设置 </a-menu-item>
    </a-menu>
    <a-row>
        <div class="" style="margin-top: 30px;">
        </div>
    </a-row>
  <a-row>
    <a-col :span="12">
        <a-row>
            <a href="" class="ant-upload ant-upload-select ant-upload-select-text" style="margin-left: 10px;">本地上传文件:</a>
            <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                <span role="button" tabindex="0" class="ant-upload">
                    <input type="file" id="inputfile" ref="inputfile" accept="" multiple="multiple" style="display: none;"  @change="changefile">
                    <button type="button" class="ant-btn" ant-click-animating-without-extra-node="false" @click="select_files">
                        <a-icon type="file-add"/>
                        <span>选择文件</span>
                    </button>
                </span>
            </div>
            <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                <span role="button" tabindex="0" class="ant-upload">
                    <span>works:</span>
                    <a-input-number id="inputNumber" v-model="multi" :min="1" :max="10"  style="margin-left: 10px;" :disabled="!multi_enale"/>
                </span>
            </div>
        </a-row>
        <a-row style="margin-top: 5px;" >
            <a-tabs default-active-key="1">
                <a-tab-pane key="1">
                    <span slot="tab"><span class="ant-badge-status-dot ant-badge-status-default" style="margin-right: 5px;"></span>待上传  {{beUploadsFiles.length}}</span>
                    <a-row style="margin-bottom: 5px;" >
                        <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                            <span role="button" tabindex="0" class="ant-upload">
                                <button type="button" class="ant-btn" ant-click-animating-without-extra-node="false" @click="upload_files" :loading="upload_status">
                                    <a-icon type="upload"/>
                                    <span>开始上传</span> 
                                </button>
                            </span>
                        </div>
                    </a-row>
                    <a-table :data-source="beUploadsFiles" :columns="files_columns"
                        class="m-manager-table__table m-manager-table__hover--none m-manager-table__choose--none" size="small"
                        :showHeader="true"  tableLayout="auto" 
                        :pagination="files_pagination"
                        bordered
                        >
                        <!-- ///0计算md5 1队列中 2 ready 3uploading 4sucess 5error -->
                        <span slot="status" slot-scope="text, record">
                            <a-badge status="default" :text="record.status.message"  v-show="record.status.status==1"/>
                            <a-badge status="processing" :text="record.status.message" v-show="record.status.status==0 ||record.status.status==2 || record.status.status==3" />
                        </span>
                        <span slot="progress" slot-scope="text, record">
                            <a-progress :percent="record.status.percentage" status="active" v-show="(record.status.status==2 ||record.status.status==0) && record.status.percentage>0"/>
                            <a-progress :percent="record.status.percentage" status="active" v-show="record.status.status==3"/>
                        </span>
                        <template slot="operation" slot-scope="text, record">
                            <a-popconfirm  title="Sure to delete?" @confirm="() => delete_file(record)">
                                <a href="javascript:;">删除</a>
                            </a-popconfirm>
                            <a-popconfirm  style="margin-left: 10px;" title="Sure to send?" @confirm="() => postMessage(record)">
                                <a href="javascript:;">上传</a>
                            </a-popconfirm>
                        </template>
                    </a-table>
                </a-tab-pane>
                <a-tab-pane key="2">
                    <span slot="tab"><span  class="ant-badge-status-dot ant-badge-status-success" style="margin-right: 5px;"></span>上传成功 {{sucessUploadsFiles.length}}</span>
                    <a-row style="margin-bottom: 5px;" >
                        <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                            <span role="button" tabindex="0" class="ant-upload">
                                <button type="button" class="ant-btn" ant-click-animating-without-extra-node="false" @click="delete_success">
                                    <a-icon type="delete"/>
                                    <span>清空</span> 
                                </button>
                            </span>
                        </div>
                    </a-row>
                    <a-table :data-source="sucessUploadsFiles" :columns="files_columns"
                        class="m-manager-table__table m-manager-table__hover--none m-manager-table__choose--none" size="small"
                        :showHeader="true"  tableLayout="auto" 
                        :pagination="files_pagination"
                        bordered
                        >
                        <span slot="status" slot-scope="text, record">
                            <a-badge status="success" :text="record.status.message" v-show="record.status.status==4" />
                        </span>
                    </a-table>
                </a-tab-pane>
                <a-tab-pane key="3">
                    <span slot="tab"><span class="ant-badge-status-dot ant-badge-status-error" style="margin-right: 5px;"></span>上传失败 {{errorUploadsFiles.length}}</span>
                    <a-row style="margin-bottom: 5px;" >
                        <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                            <span role="button" tabindex="0" class="ant-upload">
                                <button type="button" class="ant-btn" ant-click-animating-without-extra-node="false" @click="retry_upload">
                                    <a-icon type="upload"/>
                                    <span>重新上传</span> 
                                </button>
                            </span>
                        </div>
                    </a-row>
                    <a-table :data-source="errorUploadsFiles" :columns="files_columns"
                    class="m-manager-table__table m-manager-table__hover--none m-manager-table__choose--none" size="small"
                    :showHeader="true"  tableLayout="auto" 
                    :pagination="files_pagination"
                    bordered
                    >
                    <span slot="status" slot-scope="text, record">
                        <a-badge status="error" :text="record.status.message" v-show="record.status==5" />
                    </span>
                    <template slot="operation" slot-scope="text, record">
                        <a-popconfirm  title="Sure to delete this file?" @confirm="() =>retry_delete(record)">
                            <a href="javascript:;">删除</a>
                        </a-popconfirm>
                    </template>
                </a-table>
                </a-tab-pane>
            </a-tabs>
        </a-row>
    </a-col>
    <a-col :span="12">
        <a-row>
            <a href="" class="ant-upload ant-upload-select ant-upload-select-text" style="margin-left: 10px;">服务器目录:</a>
            <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                <span role="button" tabindex="0" class="ant-upload">
                    <button type="button" class="ant-btn" ant-click-animating-without-extra-node="false" @click="route_click('/')">
                        <a-icon type="rollback"/>
                        <span>返回根目录</span>
                    </button>
                </span>
            </div>
            <div class="ant-upload ant-upload-select ant-upload-select-text" style="margin-right: 30px;float: right;">
                <span role="button" tabindex="0" class="ant-upload">
                    <button type="button" class="ant-btn" ant-click-animating-without-extra-node="false" @click="mkdir">
                        <a-icon type="plus"/>
                        <span>创建目录</span>
                    </button>
                </span>
            </div>
        </a-row>
        <a-row style="margin-top: 5px;" >
            <div class="ant-breadcrumb">
                <span class="" v-for="(item, index) in server_path" :key="index">
                    <span class="ant-breadcrumb-link" v-if="index>=0 && index<=server_path.length-1">
                        <a href="javascript:;" style="margin: 0 8px;"  @click="route_click(item)">{{item}}</a>
                    </span>
                    <span class="ant-breadcrumb-separator" v-if="index>0 && index<server_path.length-1">/</span>
                </span>
            </div>
        </a-row>
        <a-row style="margin-top: 25px;" >
            <div style="width: 95%;margin: auto;">
                <a-table :data-source="filesServer" :columns="filesServer_columns" class="m-manager-table__table m-manager-table__hover--none m-manager-table__choose--none" size="small"
                    :showHeader="true"  
                    tableLayout="auto" 
                    :pagination="filesServer_pagination"
                    :customRow="filesServerRow"
                    bordered
                    style="height:500px"
                    >
                    <span slot="fstype" slot-scope="text, record"> 
                        <a-icon type="file" v-show="record.fstype=='file'"/>
                        <a-icon type="folder" v-show="record.fstype=='dir'"/>
                    </span>
                    <template slot="operation" slot-scope="text, record">
                        <a-button type="dashed"  @click="server_delete(record)" v-show="record.fstype=='file'">删除文件</a-button>

                        <!-- <a-popconfirm  style="margin-left: 10px;" title="Sure to delete?" @confirm="() => server_delete(record)" v-show="record.fstype=='file'">
                                <a href="javascript:;">删除文件</a>
                        </a-popconfirm>

                         <a-popconfirm  style="margin-left: 10px;" title="Sure to delete?" @confirm="() => server_delete_dir(record)" v-show="record.fstype=='dir'">
                                <a href="javascript:;">删除文件夹</a>
                        </a-popconfirm> -->

                        <a-button type="dashed"  @click="server_delete_dir(record)" v-show="record.fstype=='dir'">删除文件夹</a-button>
                        
                        <a target="_blank" :href="get_server_download_url(record)" v-show="record.fstype=='file'" style="margin-left: 5px;">下载文件</a>
                    </template>
                </a-table>
            </div>
            
        </a-row>
    </a-col>
  </a-row>
   <a-modal v-model="mkdir_visible" title="创建文件夹" 
    @ok="mkdir_ok"
    :maskClosable="false"
    okText="创建"
    okType="dashed"
    :destroyOnClose="true"
    cancelText='取消'
    cancelokType="dashed"
    @cancel="mkdir_cancle"
    >
      <a-input placeholder="" v-model="mkdir_dir"/>
    </a-modal>
</div>
</template>
<script>

import SparkMD5 from 'spark-md5'
    const _files_columns =[
        {
            title: '名称',
            dataIndex: 'name',
            key: 'name',
            width:250,
            align:'center'
        },
        {
            title: '大小',
            dataIndex: 'size',
            key: 'size',
            width:100,
            align:'center'
        },
        {
            title: '状态',
            scopedSlots: { customRender: 'status' } ,
            width:100,
            key: 'status',
            align:'center'
        },
        {
            title: '进度',
            scopedSlots: { customRender: 'progress' } ,
            width:220,
            key: 'progress',
            align:'center'
        },
        {
            title: '操作',
            key: 'operation',
            scopedSlots: { customRender: 'operation' },
            align:'center'
        },
    ]
    const _files_pagination ={
        size:'small',
        pageSize:10,
        showTotal:(total, range)=>{
            return `共 ${total} 个，当前${range[0]}-${range[1]}`
        }

    }
    const _filesServer_columns=[
        { 
            title: '类型',
            key: 'fstype', 
            scopedSlots: { customRender: 'fstype' } ,
            width:50,
            align:'center'
        },
        {
            title: '名称',
            dataIndex: 'name',
            key: 'name',
            align:'center',
            width:250,
        },
        {
            title: '操作',
            key: 'operation',
            scopedSlots: { customRender: 'operation' },
            align:'center'
        },
    ]
    const _filesServer_pagination ={
        size:'small',
        pageSize:10,
        showTotal:(total, range)=>{
            return `共 ${total} 个，当前${range[0]}-${range[1]}`
        }
    }
    export default {
        data() {
            return {
                beUploadsFiles:[],
                sucessUploadsFiles:[],
                errorUploadsFiles:[],
                files_columns:_files_columns,
                files_pagination:_files_pagination,
                upload_status:false,
                work_url:'https://nmgwxyy.cn/alatan/static/uploads_worker.js',
                mkdir_visible:false,
                mkdir_dir:'',
                server_path:[],
                filesServer:[],
                filesServer_columns:_filesServer_columns,
                filesServer_pagination:_filesServer_pagination,
                filesServerRow: record => ({
                    on: {
                        dblclick: (event) => {
                            this.dblclick(record);
                        },
                    }
                }),
                workers:[],
                multi:1,//多线程上传个数
                multi_enale:true,
                worker_textContent:""
            }
        },
        mounted() {
            this.get_paths()
            fetch(this.work_url,{ method:"GET",})
            .then((response) =>  response.text())
            .then((textContent) => {
                this.worker_textContent=textContent
            })          
        },
        methods:{
            //0计算md5 1队列中 2 ready 3uploading 4sucess 5error
            guid(){
                return 'xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxx'.replace(/[xy]/g, function (c) {
                    let r = Math.random() * 16 | 0,v = c == 'x' ? r : (r & 0x3 | 0x8);
                    return v.toString(16);
                })
            },
            select_files(){
                let _this=this;+
                setTimeout(function(){
                    _this.$refs.inputfile.click();
                },10)
            },
            changefile(event){
                event.srcElement.files.forEach((_file,_index) => {
                    let one_file={
                        key: _file.name,//this.guid(),
                        file:_file,
                        name:_file.name,
                        size:_file.size,
                        status:{
                            status:1,
                            message:'队列中',
                            percentage:0
                        }
                    }
                    this.beUploadsFiles.push(one_file)
                    //this.compute_hash(one_file)
                    console.log(this.beUploadsFiles)
                });
                document.getElementById('inputfile').value= ''; 
                if(this.upload_status==true){
                    this.upload_files();
                }
            },
            compute_hash(one_file){
                return new Promise((resolve)=>{
                    var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
                    file = one_file.file,
                    chunkSize = 2 * 1024 * 1024,                             // Read in chunks of 2MB
                    chunks = Math.ceil(file.size / chunkSize),
                    currentChunk = 0,
                    spark = new SparkMD5.ArrayBuffer(),
                    fileReader = new FileReader();
                    fileReader.onload = function (e) {
                        console.log('read chunk nr', currentChunk + 1, 'of', chunks);
                        spark.append(e.target.result);                   // Append array buffer
                        currentChunk++;
                        if (currentChunk < chunks) {
                            console.info(currentChunk, chunks);
                            one_file.status.percentage=Number(((currentChunk) / chunks * 100).toFixed(0))
                            loadNext();
                        } else {
                                console.log('finished loading');
                                let endMDB=spark.end()
                                console.info('computed hash', spark.end());  // Compute hash
                                one_file.key=endMDB
                                one_file.status={
                                status:1,
                                message:'队列中',
                                percentage:0
                            }
                            resolve(endMDB) 
                            
                        }
                    };
                    fileReader.onerror = function () {
                        console.warn('oops, something went wrong.');
                        resolve(false) 
                    };
                    function loadNext() {
                        var start = currentChunk * chunkSize,
                            end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
                        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
                    }
                    loadNext()
                })
            },
            delete_file(record) {
                let _find_index=this.beUploadsFiles.findIndex(item => item.key === record.key)
                if(_find_index>=0){
                    let _item=this.beUploadsFiles[_find_index]
                    if(_item.status.status==3){
                        this.$message("该项正在上传,不可删除")
                    }
                    else{
                        this.beUploadsFiles.splice(_find_index, 1); 
                    }
                }
            },
            worker_get_message(e){
                let {workid,fileid,fileid_old,data}=e.data
                let beUploadsFile_index=this.beUploadsFiles.findIndex((val)=>{
                    return val.key==fileid_old
                })
                if(beUploadsFile_index>=0){
                    this.beUploadsFiles[beUploadsFile_index].status=data
                    if(data.status==5 ||data.status==4){
                        if(data.end==true){
                            let _fileObs=this.beUploadsFiles.splice(beUploadsFile_index,1)
                            this.SetWorkderFree(workid);//其实workid是worker_index
                            this.upload_files()
                            if(data.status==5 ){ //错误的
                                this.errorUploadsFiles.push(_fileObs[0])
                            }
                            else if(data.status==4 && data.end==true){ //成功的
                                this.sucessUploadsFiles.push(_fileObs[0])
                                this.get_paths()
                            }
                        }
                    }
                }
            },
            DoNext(worker_index,_fileIndex){
                this.SetWorkderProcess(worker_index)
                this.beUploadsFiles[_fileIndex].status.status=2
                this.postMessage(worker_index,this.beUploadsFiles[_fileIndex]);
                this.upload_status=true;

            },
            postMessage(worker_index,record){
                let _Message={
                    file:record.file,
                    workid: worker_index,//this.workers[worker_index].id,
                    fileid:record.key,
                    token:this.$store.state.user.token,
                    type:'single',//single multy
                    rootdir:this.get_recent_path(),
                    usemd5:false,
                }
                this.workers[worker_index].worker.postMessage(_Message)
            },
            GetFilesbeUploadsIndex(){
                return this.beUploadsFiles.findIndex((val)=>{
                    return val.status.status==1
                })
            },
            SetWorkderProcess(worker_index){
                this.workers[worker_index].free=false
            },
            SetWorkderFree(worker_index){
                this.workers[worker_index].free=true
            },
            GetWorkderFree(){
                 let worker_index=this.workers.findIndex((val)=>{
                    return val.free==true
                })
                return worker_index
            },
            creatWorkers(){
                let blob = new Blob([this.worker_textContent]);
                for (let index = 0; index < this.multi; index++) {
                    let worker=new Worker(URL.createObjectURL(blob))
                    worker.onmessage =this.worker_get_message
                    this.workers.push({
                        worker:worker,
                        id:this.guid(),
                        free:true,
                    })
                }
            },
            upload_files(){
                this.multi_enale=false
                if(this.workers.length==0){
                    this.creatWorkers();
                }
                if(this.beUploadsFiles.length==0){
                    this.$message.info('没有可上传文件');
                    console.log("uploads end...")
                    this.upload_status=false;
                    this.multi_enale=true
                    return
                }
                //需要定时循环
                let worker_index=this.GetWorkderFree()
                let _fileIndex=this.GetFilesbeUploadsIndex()
                while(worker_index>=0 && _fileIndex>=0){
                    this.DoNext(worker_index,_fileIndex)
                    worker_index=this.GetWorkderFree()
                    _fileIndex=this.GetFilesbeUploadsIndex()
                }
                // if(_fileIndex<0){
                //     console.log("uploads end...")
                //     this.upload_status=false;
                // }
            },
            delete_success(){
                this.sucessUploadsFiles=[]//如果有任务泽需要停止任务才能删除
            },
            retry_upload(){
                this.sucessUploadsFiles=[]
                for (let index = 0; index < this.errorUploadsFiles.length; index++) {
                    let record = this.errorUploadsFiles[index];
                    record.status={
                        status:1,
                        message:'队列中',
                        percentage:0
                    }
                    this.beUploadsFiles.push(record)
                }
                this.errorUploadsFiles=[]
            },
            retry_delete(record){
                 let _findIndex=this.errorUploadsFiles.findIndex((val)=>{
                    return val.key==record.key
                })
                if(_findIndex>=0){
                    this.errorUploadsFiles.splice(_findIndex,1)
                }
            },
            route_click(_path){
                let _new_server_path=[]
                let _index=this.server_path.findIndex((_ppath)=>{
                    return _ppath==_path
                })
                if(_index>=0){
                    _new_server_path=this.server_path.slice(0,_index+1)
                    let server_path=this.get_recent_path(_new_server_path)
                    let currnt=this.get_recent_path()
                    if(server_path==currnt){

                    }
                    else{
                        this.get_paths(server_path)
                    }
                }
            },
            async dblclick(record){
                if(record.fstype=='dir'){
                    this.Topath(record.name)
                }  
            },
            Topath(_path){
                let _dir_post=(this.get_recent_path()+_path).replace('//','/')
                this.get_paths(_dir_post)
            },
            get_recent_path(server_path){
                if(server_path){
                    return (server_path.join('/')+'/').replace('//','/')
                }
                else{
                    return ([...this.server_path].join('/')+'/').replace('//','/')
                }
            },
            get_paths(_path){
                if(!_path){
                    _path=this.get_recent_path()
                }
                this.$common_apis.axios_get("/get_path?",{
                    path:_path
                },true).then(_result => {
                    if(_result){
                        this.filesServer=[]
                        let filesServer=[]
                        let key=0
                        _result.dirs.forEach(_dir => {
                            filesServer.push({
                                fstype:'dir',
                                name:_dir.file,
                                key:key,
                                needpassword:_dir.password
                            })
                            key+=1

                        });
                        _result.files.forEach(_file => {
                            filesServer.push({
                                fstype:'file',
                                name:_file,
                                key:key,
                                needpassword:false
                            })
                            key+=1
                        });
                        this.filesServer=filesServer
                        this.server_path=_result.path
                    }
                    else{
                        this.$message.error(_data.message)
                    }
                    this.$forceUpdate()
                });
            },
            async mkdir(){
                this.mkdir_dir=''
                this.mkdir_visible=true
                this.WaitInputDirName =new Promise((resolve)=>{this.WaitInputDirName_resolve=resolve;});
                let inputOK=await this.WaitInputDirName
                if(inputOK){
                    this.post_delete('mk_dir',this.mkdir_dir)
                    
                }
            },
            mkdir_ok(){
                this.mkdir_visible=false
                this.WaitInputDirName_resolve(true);
            },
            mkdir_cancle(){
                this.mkdir_visible=false
                this.WaitInputDirName_resolve(false);
            },
            server_delete(record){
                this.post_delete('del_file',record.name)
            },
            server_delete_dir(record){
                this.post_delete('del_dir',record.name)
            },
            post_delete(_route,_name){
                let _dir_post=this.get_recent_path()+_name
                this.$common_apis.axios_post(`/${_route}`,{
                    path:_dir_post
                },true).then(_result => {
                    if(_result){
                        this.get_paths()
                    }
                    else{
                        this.$message.error(_data.message)
                    }
                    this.$forceUpdate()
                });
            },
            get_server_download_url(record){
                let _dir_post=this.get_recent_path()+record.name
                let _downfile=`${window.Glod.publicurl}${this.$store.state.user.user.id}${_dir_post}`
                return _downfile
            },
        }
  }
</script>
<style >
.ant-separator-root:hover {
  color: #40a9ff;
  cursor: pointer;
}
</style>